#! /usr/bin/env python3

"""
视频剪辑节目
"""
import os.path

from ui.ui_clip import Ui_cut
from .clip_header import QCheckBoxHeader
from . import view_style
from .view_bar import CViewBar
from .custom_widget import CViewSpeed
from PySide2.QtWidgets import *
from PySide2.QtCore import Qt
from model.clip_file import clipfile, clip_slice


class ClipMediaType:
    Video = 0
    Audio = 1


class CViewClip(QWidget, Ui_cut):
    header_field = ['全选', '文件名', '起始时刻', '结束时刻', '播放速度', '删除']
    col_checkbox = 0
    col_name = 1
    col_start = 2
    col_end = 3
    col_speed = 4
    col_remove = 5

    def __init__(self, parent=None):
        super(CViewClip, self).__init__(parent=parent)
        self.setupUi(self)
        self.bar = CViewBar(self)
        self.style = view_style.factory()
        self.duration_v = 0
        self.duration_a = 0
        self.last_path = '.'
        self.init_ui()
        self.init_action()

    def init_ui(self):
        self.init_media_table()
        self.style.set_clip_style(self.tw_video, self.tw_audio)

    def init_media_table(self):
        self.tw_video.setHorizontalHeader(QCheckBoxHeader())
        self.tw_audio.setHorizontalHeader(QCheckBoxHeader())
        self.tw_video.setColumnCount(len(self.header_field))
        self.tw_audio.setColumnCount(len(self.header_field))
        self.tw_video.setHorizontalHeaderLabels(self.header_field)
        self.tw_audio.setHorizontalHeaderLabels(self.header_field)
        self.tw_video.hideColumn(self.col_checkbox)
        self.tw_audio.hideColumn(self.col_checkbox)
        self.tw_video.hideColumn(self.col_speed)
        self.tw_audio.hideColumn(self.col_speed)

    def init_action(self):
        self.btn_video.clicked.connect(self.choose_file)
        self.btn_audio.clicked.connect(self.choose_file)
        clipfile.VideoFileChanged.connect(lambda p: self.update_media_file(ClipMediaType.Video, p))
        clipfile.AudioFileChanged.connect(lambda p: self.update_media_file(ClipMediaType.Audio, p))
        self.btn_v_clip.clicked.connect(lambda: self.add_media_clip(ClipMediaType.Video))
        self.btn_a_clip.clicked.connect(lambda: self.add_media_clip(ClipMediaType.Audio))
        self.btn_clip.clicked.connect(self.to_clip)

    def choose_file(self):
        caption = "选择视频文件"
        ftr = "视频文件 (*.mp4)"
        file_cb = clipfile.add_video_file
        if self.sender() == self.btn_audio:
            caption = "选择音频文件"
            ftr = "音频文件 (*.mp3)"
            file_cb = clipfile.add_audio_file
        file = QFileDialog.getOpenFileName(self, caption, self.last_path, ftr)
        if file[0] == "":
            return
        print(file[0])
        self.last_path = os.path.dirname(file[0])
        file_cb(file[0])

    def update_media_file(self, t: int, files: set):
        cb = self.cb_video if t == ClipMediaType.Video else self.cb_audio
        cb.clear()
        # file_basename = [os.path.basename(item) for item in files]
        cb.addItems(files)

    @staticmethod
    def make_media_duration(pose_s: str, pose_e: str) -> int:
        d_s = pose_s.split(':')
        d_e = pose_e.split(':')
        ts_e = int(d_e[0]) * 3600 + int(d_e[1]) * 60 + int(d_e[2])
        ts_s = int(d_s[0]) * 3600 + int(d_s[1]) * 60 + int(d_s[2])
        return ts_e - ts_s

    @staticmethod
    def update_duration_msg(label: QLabel, duration: int):
        msg = '{:0>2d}:{:0>2d}:{:0>2d}'.format(duration//3600, duration%3600//60, duration%3600%60)
        label.setText(msg)

    def add_media_clip(self, t: int):
        cb: QComboBox = self.cb_video if t == ClipMediaType.Video else self.cb_audio
        if cb.currentIndex() < 0:
            QMessageBox.critical(self, "添加失败", "\r\n请先通过添加多媒体按钮添加文件\t\r\n", QMessageBox.Ok, QMessageBox.Ok)
            return
        widget = self.tw_video if t == ClipMediaType.Video else self.tw_audio
        file_name = cb.currentText()
        pose_s = self.te_video.text() if t == ClipMediaType.Video else self.te_audio.text()
        pose_e = self.te_video_e.text() if t == ClipMediaType.Video else self.te_audio_e.text()
        print(file_name, " ", pose_s, " ", pose_e)
        line = clip_slice(file_name, pose_s, pose_e, 0)
        duration = self.make_media_duration(pose_s, pose_e)
        if duration <= 0:
            QMessageBox.critical(self, "添加失败", "\r\n结束时间不能早于开始时间\t\r\n", QMessageBox.Ok, QMessageBox.Ok)
            return
        if t == ClipMediaType.Video:
            self.duration_v += duration
            self.update_duration_msg(self.ld_video, self.duration_v)
        else:
            self.duration_a += duration
            self.update_duration_msg(self.ld_audio, self.duration_a)
        self.add_clip_line(widget, line)

    def add_clip_line(self, widget: QTableWidget, line: clip_slice):
        def make_item(text: str) -> QTableWidgetItem:
            item = QTableWidgetItem(text)
            item.setTextAlignment(Qt.AlignCenter)
            return item

        n_row = widget.rowCount()
        widget.setRowCount(n_row + 1)
        widget.setItem(n_row, CViewClip.col_name, make_item(line.name))
        widget.setItem(n_row, CViewClip.col_start, make_item(line.pose_s))
        widget.setItem(n_row, CViewClip.col_end, make_item(line.pose_e))
        speed_widget: CViewSpeed = CViewSpeed(speed=line.speed)
        widget.setCellWidget(n_row, CViewClip.col_speed, speed_widget)
        widget.setRowHeight(n_row, speed_widget.height()+10)

        rm_label = QLabel("<a href='#'>删除本行</a>")
        rm_label.setAlignment(Qt.AlignCenter)
        remove_func = self.remove_video_line if widget == self.tw_video else self.remove_audio_line
        rm_label.linkActivated.connect(remove_func)
        widget.setCellWidget(n_row, CViewClip.col_remove, rm_label)

    def to_clip(self):
        out_file = QFileDialog.getSaveFileName(self, "保存合成文件", ".", "视频文件 (*.mp4)")
        if out_file[0] == '':
            return
        clipfile.clip_and_save(out_file[0], self.get_video_clip(), self.get_audio_clip(), self.cb_mute.isChecked())
        self.bar.show()

    def get_media_clip(self, widget: QTableWidget) -> list:
        n_row = widget.rowCount()
        clips = list()
        for r in range(n_row):
            file_name = widget.item(r, self.col_name).text()
            pose_s = widget.item(r, self.col_start).text()
            pose_e = widget.item(r, self.col_end).text()
            line = clip_slice(file_name, pose_s, pose_e, widget.cellWidget(r, self.col_speed).value)
            clips.append(line)
        return clips if len(clips) else None

    def get_video_clip(self) -> list:
        return self.get_media_clip(self.tw_video)

    def get_audio_clip(self) -> list:
        return self.get_media_clip(self.tw_audio)

    @staticmethod
    def sub_duration(tw: QTableWidget, duration: int, label: QLabel) -> int:
        row = tw.currentRow()
        pose_s = tw.item(row, CViewClip.col_start).text()
        pose_e = tw.item(row, CViewClip.col_end).text()
        ts = CViewClip.make_media_duration(pose_s, pose_e)
        CViewClip.update_duration_msg(label, duration - ts)
        return ts

    def remove_video_line(self):
        row = self.tw_video.currentRow()
        self.duration_v -= self.sub_duration(self.tw_video, self.duration_v, self.ld_video)
        self.tw_video.removeRow(row)

    def remove_audio_line(self):
        row = self.tw_audio.currentRow()
        self.duration_v -= self.sub_duration(self.tw_audio, self.duration_a, self.ld_audio)
        self.tw_audio.removeRow(row)
